/**********************************************************************************************************************
 * @file    qlcommon.h
 * @author  Queclink Hubert.Lee
 * @date    2018-04-12
 * @brief   Queclink FreeRTOS Software Development Kit internal data structure definition.
 * @ingroup common
 *
 * Copyright (C) 2018 Queclink Wireless Solutions (ShenZhen) Co., Ltd. All Rights Reserved.
 *
 * @attention
 *
 * @usage
 *
 *********************************************************************************************************************/


#ifndef __QLCOMMON_H
#define __QLCOMMON_H

/* includes ---------------------------------------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stddef.h>
#include <stdbool.h>
#include <stdlib.h>
#include <ctype.h>
#include <qlibc/memory.h>
#include <qlibc/stdlib.h>
#include <qlibc/string.h>
#include <aadl/misc.h>
#include <public/list.h>
#include <public/errno.h>
#include <cmsis_os2.h>
#include <FreeRTOS.h>
#include <list.h>
#include <task.h>
#include <semphr.h>

#define qlmalloc(size)  pvPortMalloc(size)
#define qlfree(ptr)     vPortFree(ptr)


#ifndef _SSIZE_T
#define _SSIZE_T
typedef signed int ssize_t;
#endif


#ifdef __cplusplus
extern "C" {
#endif


//#include <qlsdk/qltrace.h>
//#include <qlcomm/request.h>
//#include <qlcomm/notify.h>
//#include <qlcomm/event.h>
#include <qlcomm/misc.h>

#include "bsp.h"



/* log level definition */
#define LOG_FATAL       "0" /* 关键的,重大的,致命的 */
#define LOG_EMERG       "0" /* system is unusable */
#define LOG_ALERT       "1" /* action must be taken immediately */
#define LOG_CRIT        "2" /* critical conditions */
#define LOG_ERROR       "3" /* error conditions */
#define LOG_ERR         "3" /* error conditions */
#define LOG_WARNING     "4" /* warning conditions */
#define LOG_WARN        "4" /* warning conditions */
#define LOG_NOTICE      "5" /* normal but significant condition */
#define LOG_INFO        "6" /* informational */
#define LOG_DEBUG       "7" /* debug-level messages */

#define LOG_FATAL_C       '0' /* 关键的,重大的,致命的 */
#define LOG_EMERG_C       '0' /* system is unusable */
#define LOG_ALERT_C       '1' /* action must be taken immediately */
#define LOG_CRIT_C        '2' /* critical conditions */
#define LOG_ERR_C         '3' /* error conditions */
#define LOG_ERROR_C       '3' /* error conditions */
#define LOG_WARNING_C     '4' /* warning conditions */
#define LOG_WARN_C        '4' /* warning conditions */
#define LOG_NOTICE_C      '5' /* normal but significant condition */
#define LOG_INFO_C        '6' /* informational */
#define LOG_DEBUG_C       '7' /* debug-level messages */

#define LOG_ALL         LOG_DEBUG
#define LOG_OFF         "n" /* 关闭LOG打印功能 */


#define qltrace(fmt, args...)       qltrace_output(fmt, ##args)
#define LOG_MACRO(lvl_str)   ("[" LOG_TAG lvl_str)
#define qltrace_output(fmt, ...)  \
do {    \
    char loglevel = (char)*fmt; \
    switch(loglevel) {         \
    case LOG_ERROR_C: elog_output(ELOG_LVL_ERROR,  LOG_MACRO("_E]"), __FILE_NAME__, __FUNCTION__, __LINE__, fmt + 1, ##__VA_ARGS__); break; \
    case LOG_WARN_C:  elog_output(ELOG_LVL_WARN,   LOG_MACRO("_W]"), __FILE_NAME__, __FUNCTION__, __LINE__, fmt + 1, ##__VA_ARGS__); break; \
    case LOG_INFO_C:  elog_output(ELOG_LVL_INFO,   LOG_MACRO("_I]"), __FILE_NAME__, __FUNCTION__, __LINE__, fmt + 1, ##__VA_ARGS__); break; \
    case LOG_DEBUG_C: elog_output(ELOG_LVL_DEBUG,  LOG_MACRO("_D]"), __FILE_NAME__, __FUNCTION__, __LINE__, fmt + 1, ##__VA_ARGS__); break; \
    }   \
} while(0)

#define qlprintf(fmt, args...)     log_d(fmt, ##args) 	
#define record_syserr(str)         log_e(str);


#if 0
#warning "NEED watchdog feed implement"
void lib_watchdog_feed(void);
#endif


/*
 * 若使用 DELETED,ACTIVATED 就可以解决问题, 请不要使用 PREDELETE 状态.
 */
#define DELETED     0       /* deleted(inactivated), 删除的(失活的) */
#define PREDELETE   2       /* pre-delete, 预删除(正在删除) */
#define ACTIVATED   1       /* activated, 激活的,有效的 */

/*
 * 由于 bitwise 操作不具有线程安全性, 写操作务必使用 set_bitwise 宏完成.
 */
#define set_bitwise(word, bit_value) \
    do { \
        taskENTER_CRITICAL(); \
        word = bit_value; \
        taskEXIT_CRITICAL(); \
    } while(0)

/*
 * ticks convert to ms
 */
#define _TICKS2MS(ticks)   ((TickType_t)(ticks) * portTICK_PERIOD_MS)

/*
 * ms convert to ticks
 * 注意 SDK 内部不可直接使用 qlsdk.h 中的 MS2TICKS
 */
#define _MS2TICKS(ms)   (((TickType_t)(ms) / portTICK_PERIOD_MS) + \
                         (((TickType_t)(ms) % portTICK_PERIOD_MS) ? 1 : 0))

/*
 * seconds convert to ticks, ignore remainder
 * 注意 SDK 内部不可直接使用 qlsdk.h 中的 SEC2TICKS
 */
#define _SEC2TICKS(sec) ((TickType_t)(sec)*1000 / portTICK_PERIOD_MS)


/* !!! Please use this macro to feed watchdog in the task of SDK !!!
 * 任务中不允许直接进行硬件看门狗喂狗, 任务中必须使用该宏进行喂狗, 同时要注意:
 * 1. 不可以在 ISR 中喂狗; 2. SDK 任务中尽量不要进行喂狗, 非常必要时才进行喂狗. */
#include "bsp/inc/bsp_wdt.h"
#define feedwdg()   bsp_wdt_feed()


extern void *qltask_param_get(void);

extern void *qltask_request_ptr_get(void);

extern int qltask_request_ptr_set(void *ptr);

extern void *qltask_event_ptr_get(void);

extern int qltask_event_ptr_set(void *ptr);




/* dead here, wait for watchdog reset */
#define noreturn()  do { \
                        vTaskSuspendAll(); \
                        for (;;) ; \
                    } while(0)

#define INVALID_ID          (-1)

#define NOTIMING    0       /* 未开始计时 */

/* FreeRTOS task stack size, unit byte */
#define STACK_BYTES(bytes)  ((bytes)/4)

#define ARRAY_COUNT(array)  (sizeof(array) / sizeof(array[0]))

#define set_bit(word, bit)          (word) |= (1ul << (bit))
#define clr_bit(word, bit)          (word) &= ~(1ul << (bit))
#define get_bit_status(word, bit)   ((0 != ((word) & (1ul << (bit)))) ? 1 : 0)

#define array_element_address_get(array, element, value) \
    do { \
        int i; \
        for (i=0; i < ARRAY_COUNT(array); i++) { \
            if (value == array[i].element) \
                return &array[i]; \
        } \
        return NULL; \
    } while(0)
    


#ifdef __cplusplus
}
#endif

#endif /* __QLCOMMON_H */
